package cn.com.surker.lab.service.impl;

import cn.com.surker.base.strength.dao.BaseStrengthDao;
import cn.com.surker.base.system.dao.SysLineDao;
import cn.com.surker.base.system.entity.SysLine;
import cn.com.surker.common.MessageCenterException;
import cn.com.surker.database.JDBCTemplateCache;
import cn.com.surker.enums.StateEnum;
import cn.com.surker.enums.production.indent.ProTypeEnum;
import cn.com.surker.lab.dao.LabExpendUploadDao;
import cn.com.surker.lab.dao.LabExpendUploadLineDao;
import cn.com.surker.lab.dao.LabLevelConstructDao;
import cn.com.surker.lab.entity.LabExpendUpload;
import cn.com.surker.lab.entity.LabExpendUploadLine;
import cn.com.surker.lab.service.LabExpendUploadLineService;
import cn.com.surker.lab.vo.LabExpendUploadLineVo;
import cn.com.surker.production.dao.ProductionIndentDao;
import cn.com.surker.production.entity.ProductionIndent;
import cn.com.surker.spring.RestResultDto;
import cn.com.surker.util.DateUtil;
import cn.com.surker.util.StringUtils;
import cn.com.surker.workcon.common.RecipeTranEntity;
import cn.com.surker.workcon.service.RecipeService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.*;

/**
 * <p>
 * 技术上传配合详情表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2024-09-23
 */
@Service
public class LabExpendUploadLineServiceImpl extends ServiceImpl<LabExpendUploadLineDao, LabExpendUploadLine> implements LabExpendUploadLineService {

	@Resource
	private LabExpendUploadLineDao labExpendUploadLineDao;
	@Resource
	private LabExpendUploadDao labExpendUploadDao;
	@Resource
	private ProductionIndentDao productionIndentDao;
	@Resource
	private BaseStrengthDao baseStrengthDao;
	@Resource
	private LabLevelConstructDao levelConstructDao;
	@Resource
	private SysLineDao lineDao;
	@Resource
	private RecipeService recipeService;

	@Override
	public List<LabExpendUploadLine> findByPId(Long uploadId) {
		if (StringUtils.isNull(uploadId))
			throw new MessageCenterException("参数错误");
		QueryWrapper<LabExpendUploadLine> qw = new QueryWrapper<>();
		qw.eq("status", StateEnum.ENABLED.getCode());
		qw.eq("lab_expend_upload_id", uploadId);
		qw.orderByAsc("id");
		List<LabExpendUploadLine> uploadLines = labExpendUploadLineDao.selectList(qw);
		return uploadLines;
	}

	/**
	 * 根据配合比查询信息
	 * @param constructId
	 * @return
	 */
	public List<LabExpendUploadLine> findByConstruct(Long constructId) {
		if (StringUtils.isNull(constructId))
			throw new MessageCenterException("参数错误");
		List<LabExpendUploadLine> uploadLines = labExpendUploadLineDao.findByConstruct(constructId);
		return uploadLines;
	}

	@Override
	public LabExpendUploadLine findByLineId(Long indentId, Long lineId) {
		if (indentId == null || lineId == null) {
			return null;
		}
		LabExpendUploadLine line = labExpendUploadLineDao.findByLineId(indentId, lineId);
		return line;
	}

	/**
	 * 批量保存上传配合比详情
	 * @param list
	 * @return
	 */
	public RestResultDto saveBatchLine(LabExpendUpload expendUpload, List<LabExpendUploadLine> list) {
		if (expendUpload == null || StringUtils.isNull(expendUpload.getId()) || list == null || list.size() == 0)
			throw new MessageCenterException("参数错误");
		if (StringUtils.isNull(expendUpload.getIndentId()))
			throw new MessageCenterException("任务单信息为空");
		ProductionIndent indent = productionIndentDao.selectById(expendUpload.getIndentId());
		if (indent == null || indent.getStatus().intValue() == 1 || indent.getType() == ProTypeEnum.END.getCode())
			throw new MessageCenterException("任务单不存在或已被禁用、供毕");

		Date nowDate = new Date();
		QueryWrapper<LabExpendUploadLine> uploadLineQuery = new QueryWrapper<>();
		uploadLineQuery.eq("status", 0);
		uploadLineQuery.eq("lab_expend_upload_id", expendUpload.getId());
		Integer total = labExpendUploadLineDao.selectCount(uploadLineQuery);
		if (total > 0) {
			UpdateWrapper<LabExpendUploadLine> updateWrapper = new UpdateWrapper<>();
			updateWrapper.set("status", 1);
			updateWrapper.set("remark", "覆盖新增配比详情");
			updateWrapper.set("update_time", DateUtil.convertString(nowDate));
			updateWrapper.set("updator", expendUpload.getCreator());
			updateWrapper.eq("lab_expend_upload_id", expendUpload.getId());
			updateWrapper.eq("status", 0);
			labExpendUploadLineDao.update(new LabExpendUploadLine(), updateWrapper);
		}

		List<LabExpendUploadLine> tempList = new ArrayList<>();
		List<Long> controlStorageList = new ArrayList<>();
		for (int i = 0; i < list.size(); i++) {
			LabExpendUploadLine uploadLine = list.get(i);
			Double realDosage = StringUtils.convertDouble(uploadLine.getConstructNum()) + StringUtils.convertDouble(uploadLine.getDosage());
			if (StringUtils.isNull(uploadLine.getLineId()))
				throw new MessageCenterException("子项" + (i + 1) + "生产线为空");
			if (StringUtils.isNull(uploadLine.getMaterialType()))
				throw new MessageCenterException("子项" + (i + 1) + "材料类型为空");
			if (StringUtils.isNull(uploadLine.getMaterialType()))
				throw new MessageCenterException("子项" + (i + 1) + "材料为空");
			if (realDosage < 0)
				throw new MessageCenterException("子项" + (i + 1) + "实际用量不能小于0");
			if (StringUtils.isNull(uploadLine.getStandNum()) || uploadLine.getStandNum() < 0)
				throw new MessageCenterException("子项" + (i + 1) + "砂浆用量不能小于0");
			if (StringUtils.isNull(uploadLine.getErpStorageId()))
				throw new MessageCenterException("子项" + (i + 1) + "ERP材料仓位为空");
			if (StringUtils.isNull(uploadLine.getControlStorageId()))
				throw new MessageCenterException("子项" + (i + 1) + "工控材料仓位为空");
			if (controlStorageList.contains(uploadLine.getControlStorageId()))
				throw new MessageCenterException("工控仓位存在重复上传" + uploadLine.getControlStorage());
			uploadLine.setCreateTime(nowDate);
			uploadLine.setCreator(expendUpload.getCreator());
			uploadLine.setRealDosage(realDosage);
			uploadLine.setLabExpendUploadId(expendUpload.getId());
			tempList.add(uploadLine);
			controlStorageList.add(uploadLine.getControlStorageId());
		}
		if (tempList == null ||tempList.size() == 0)
			throw new MessageCenterException("上传工控配合比材料子项为空");
		Integer code = labExpendUploadLineDao.saveBatch(tempList);
		if (code > 0) {
//			if (expendUpload.getIsUpload() == UploadTypeEnum.DONE.getCode()) {//上传工控代码
//				Recipe recipe = new Recipe(expendUpload.getCode(), flag, "", "", "", "", indent.getSlumps(),
//						expendUpload.getMixTime(), scale, indent.getTech(), "", "", nowDate,
//						flag, indent.getRemark(), list);
//			} else {
				return RestResultDto.success("更保存配合比成功,等待上传工控~！", expendUpload);
//			}
		}
		throw new MessageCenterException("保存上传工控配合比材料子项失败");
	}

	/**
	 * 查询上传材料信息
	 * @param uploadId
	 * @return
	 */
	public List<LabExpendUploadLineVo> findExpendUploadList(Long uploadId) {
		if (StringUtils.isNull(uploadId))
			return null;
		List<LabExpendUploadLineVo> uploadLines = labExpendUploadLineDao.findExpendUploadList(uploadId);
		if (uploadLines == null || uploadLines.size() == 0)
			return null;
		return uploadLines;
	}

	@Override
	public Integer findExistSn(Long orgId, Integer type, Long uploadId) {
		Integer total = labExpendUploadLineDao.findExistSn(orgId, type, uploadId);
		return total;
	}

	@Override
	public Integer findExistSnDosage(Long orgId, Integer type, Long uploadId) {
		Integer snDosage = labExpendUploadLineDao.findExistSnDosage(orgId, type, uploadId);
		return snDosage;
	}

	/**
	 * 配合比材料详情转换工控下料数据
	 * @param uploadLines
	 * @return
	 */
	private List<Map<String, Object>> convertList(List<LabExpendUploadLineVo> uploadLines) {
		List<Map<String, Object>> list = new ArrayList<>();
		for (int i = 0; i < uploadLines.size(); i++) {
			LabExpendUploadLineVo line = uploadLines.get(i);
			if (StringUtils.isNull(line.getMaterialName()) || line.getRealDosage() < 0)
				continue;
			Map<String, Object> map = new HashMap<>();
			map.put("materialId", line.getMaterialId());
			map.put("controlId", line.getControlStorageId());
			map.put("materialType", line.getMaterialType());
			map.put("storageId", line.getErpStorageId());
			map.put("name", line.getControlMaterial());
			map.put("value", line.getRealDosage());//砼用量
			map.put("standValue", line.getStandNum());//砂浆用量
			list.add(map);
		}
		return list;
	}

	private List<RecipeTranEntity> convertList2(List<LabExpendUploadLineVo> uploadLines) {
		List<RecipeTranEntity> list = new ArrayList<>();
		for (int i = 0; i < uploadLines.size(); i++) {
			LabExpendUploadLineVo line = uploadLines.get(i);
			if (StringUtils.isNull(line.getMaterialName()) || line.getRealDosage() < 0)
				continue;
			RecipeTranEntity recipeTranEntity = new RecipeTranEntity();
			recipeTranEntity.setMaterialId(line.getMaterialId());
			recipeTranEntity.setControlStorageId(line.getControlStorageId());
			recipeTranEntity.setMaterialType(line.getMaterialType());
			recipeTranEntity.setErpStorageId(line.getErpStorageId());
			recipeTranEntity.setControlMaterial(line.getControlMaterial());
			recipeTranEntity.setControlStorage(line.getControlStorage());
			recipeTranEntity.setConcreteDosage(line.getRealDosage());
			recipeTranEntity.setStandDosage(line.getStandNum());
			list.add(recipeTranEntity);
		}
		return list;
	}

	/**
	 * 上传配合比
	 * @param line
	 * @param params
	 * @return
	 */
	private Long insertUploadExpend(SysLine line, Map<String, Object> params, Map<String, Object> standParams) {
		if (params == null || params.keySet().size() == 0)
			return -1l;
		if (line.getProducer().equals("中青林")) {
			String keySql = "";
			String valSql = "";
			Object[] obj = new Object[params.keySet().size()];
			Integer index = 0;
			for (String key : params.keySet()) {
				keySql += key + ",";
				valSql += "?,";
				obj[index] = params.get(key);
				index++;
			}
			keySql = keySql.substring(0, keySql.length() - 1);
			valSql = valSql.substring(0, valSql.length() - 1);
			String sql = "insert into Recipe (" + keySql + ") values (" + valSql + ")";
			String standSql = "";
			index = 0;
			if (standParams != null && standParams.keySet().size() > 0) {
				keySql = "";
				valSql = "";
				Object[] standObj = new Object[standParams.keySet().size()];
				Integer standIndex = 0;
				for (String key : standParams.keySet()) {
					keySql += key + ",";
					valSql += "?,";
					obj[index] = standParams.get(key);
					index++;
				}
				keySql = keySql.substring(0, keySql.length() - 1);
				valSql = valSql.substring(0, valSql.length() - 1);
				standSql = "insert into Recipe (" + keySql + ") values (" + valSql + ")";
			}
			JdbcTemplate jdbcTemplate = JDBCTemplateCache.getLineTransactionJdbcTemp(line);
			try {
				JDBCTemplateCache.beginTransaction(line.getId() + "", 0);//开启
				if (standParams != null && standParams.keySet().size() > 0 && !StringUtils.isNull(standSql)) {
					Integer code = jdbcTemplate.update(standSql);
					if (code < 1)
						return -1l;
				}
				KeyHolder keyHolder = new GeneratedKeyHolder();
				jdbcTemplate.update(new PreparedStatementCreator() {
					public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
						PreparedStatement ps = connection.prepareStatement(sql, new String[]{"ID"});
						for (int i = 0; i < obj.length; i++) {
							ps.setObject(i + 1, obj[i]);
						}
						return ps;
					}
				}, keyHolder);
				Long taskId = keyHolder.getKey().longValue();
				if (taskId > 1) {
					JDBCTemplateCache.commitTranLine(line.getId() + "", 0);//提交事务
					return taskId;
				}
				return -1l;
			} catch (Exception e) {
				e.printStackTrace();
				JDBCTemplateCache.rollbackLine(line.getId() + "", 0);//回滚事务
				return -1l;
			}
		}
		return -1l;
	}

	/**
	 * 配合比转换
	 * @return
	 */
	private Map<String, Object> convertYaboParams(Long controlLineId, String code, String tag, String betLev, String filter, String freeze,
												  String season, String lands, Integer mixLast, String scale,
												  String otherReq, String exper, String assoss, String datTim,
												  String flag, String note, List<Map<String, Object>> list, Integer isStand) {
		Map<String, Object> paramsMap = new LinkedHashMap<>();
		if (isStand == 1)
			code = "R" + code;
		paramsMap.put("station", controlLineId);
		paramsMap.put("code", code);
		paramsMap.put("tag", tag);
		paramsMap.put("betLev", betLev);
		paramsMap.put("filter", filter);
		paramsMap.put("freeze", freeze);
		paramsMap.put("season", season);
		paramsMap.put("lands", lands);
		paramsMap.put("mixLast", mixLast);
		paramsMap.put("scale", scale);
		paramsMap.put("otherReq", otherReq);
		paramsMap.put("exper", exper);
		paramsMap.put("assoss", assoss);
		paramsMap.put("datTim", datTim);
		paramsMap.put("flag", flag);
		paramsMap.put("note", note);
		Integer dosageFlag = 0;//是否存在用量信息
		if (list != null && list.size() > 0) {
			List<String> keyList = new ArrayList<>();
			for (int i = 0; i < list.size(); i++) {
				Map<String, Object> map =list.get(i);
				String materialId = StringUtils.convertString(map.get("materialId"));//材料
				String materialType = StringUtils.convertString(map.get("materialType"));//材料类型
				String controlId = StringUtils.convertString(map.get("controlId"));//工控仓位
				Double realDosage = StringUtils.convertDouble(map.get("value"));//实际下料
				if (isStand == 1)
					realDosage = StringUtils.convertDouble(map.get("standValue"));//砂浆实际下料
				String storageId = StringUtils.convertString(map.get("storageId"));//ERP仓位
				String materialName = StringUtils.convertString(map.get("name"));//ERP仓位
				if (realDosage > 0) {//验证是否存在重复的
					String key = materialId + "_" + controlId + "_" + materialType + "_" + storageId;
					if (keyList.contains(key)) {
						realDosage = 0.0;
					} else {
						keyList.add(key);
						if (dosageFlag == 0)
							dosageFlag = 1;
					}
				} else {
					realDosage = 0.0;
				}
				String mKey = "m" + (i + 1);
				String uValue = "u" + (i + 1);
				paramsMap.put(mKey, materialName);
				paramsMap.put(uValue, realDosage);
			}
		}
		if (dosageFlag == 0)
			return null;
		return paramsMap;
	}

}